package com.inspur.edp.common.expr.visitor.type;

import com.inspur.edp.common.expr.ast.CompileUnitParser;
import com.inspur.edp.common.expr.ast.CompileUnitVisitor;
import com.inspur.edp.common.expr.exception.ExpressException;

import java.util.HashMap;
import java.util.Map;


/**
 * @author lizhaorui
 * @description TODO
 * @date 2024/6/3 16:03
 */
public class PrimitiveTypeVisitor {

    private static PrimitiveTypeVisitor instance;

    private Map<Class, PrimitiveTypeInternalVisitor> visitMap = new HashMap<>();

    public static PrimitiveTypeVisitor getInstance() {
        if (instance == null) {
            synchronized (PrimitiveTypeVisitor.class) {
                if (instance == null) {
                    PrimitiveTypeVisitor temp = new PrimitiveTypeVisitor();
                    temp.visitMap.put(CompileUnitParser.StringTypeContext.class, new StringTypeVisitor());
                    temp.visitMap.put(CompileUnitParser.BooleanTypeContext.class, new BooleanTypeVisitor());
                    temp.visitMap.put(CompileUnitParser.IntTypeContext.class, new IntTypeVisitor());
                    temp.visitMap.put(CompileUnitParser.LongTypeContext.class, new LongTypeVisitor());
                    temp.visitMap.put(CompileUnitParser.FloatTypeContext.class, new FloatTypeVisitor());
                    temp.visitMap.put(CompileUnitParser.DoubleTypeContext.class, new DoubleTypeVisitor());
                    temp.visitMap.put(CompileUnitParser.AnyTypeContext.class, new AnyTypeVisitor());
                    instance=temp;
                }
            }
        }
        return instance;
    }

    public static String visit(CompileUnitParser.PrimitiveTypeEnumContext ctx, CompileUnitVisitor compileUnitVisitor) {
        PrimitiveTypeVisitor manager = PrimitiveTypeVisitor.getInstance();
        Class cls = ctx.getClass();
        if (manager.visitMap.containsKey(cls)) {
            PrimitiveTypeInternalVisitor visitor = manager.visitMap.get(cls);
            return visitor.visit(ctx, compileUnitVisitor);
        } else {
            throw new ExpressException("not support primitive type " + cls.getName());
        }
    }

    interface PrimitiveTypeInternalVisitor {
        String visit(CompileUnitParser.PrimitiveTypeEnumContext ctx, CompileUnitVisitor visitor);
        String getTypeName(CompileUnitParser.PrimitiveTypeEnumContext ctx);
    }

    static class StringTypeVisitor implements PrimitiveTypeInternalVisitor {

        @Override
        public String visit(CompileUnitParser.PrimitiveTypeEnumContext ctx, CompileUnitVisitor visitor) {
            return visitor.visitStringType((CompileUnitParser.StringTypeContext) ctx).toString();
        }

        @Override
        public String getTypeName(CompileUnitParser.PrimitiveTypeEnumContext ctx) {
            return ((CompileUnitParser.StringTypeContext) ctx).String().getText();
        }
    }

    static class BooleanTypeVisitor implements PrimitiveTypeInternalVisitor {

        @Override
        public String visit(CompileUnitParser.PrimitiveTypeEnumContext ctx, CompileUnitVisitor visitor) {
           return visitor.visitBooleanType((CompileUnitParser.BooleanTypeContext) ctx).toString();
        }

        @Override
        public String getTypeName(CompileUnitParser.PrimitiveTypeEnumContext ctx) {
            return ((CompileUnitParser.BooleanTypeContext) ctx).Boolean().getText();
        }
    }

    static class IntTypeVisitor implements PrimitiveTypeInternalVisitor {

        @Override
        public String visit(CompileUnitParser.PrimitiveTypeEnumContext ctx, CompileUnitVisitor visitor) {
            return visitor.visitIntType((CompileUnitParser.IntTypeContext) ctx).toString();
        }

        @Override
        public String getTypeName(CompileUnitParser.PrimitiveTypeEnumContext ctx) {
            return ((CompileUnitParser.IntTypeContext) ctx).Int().getText();
        }
    }

    static class LongTypeVisitor implements PrimitiveTypeInternalVisitor {

        @Override
        public String visit(CompileUnitParser.PrimitiveTypeEnumContext ctx, CompileUnitVisitor visitor) {
            return visitor.visitLongType((CompileUnitParser.LongTypeContext) ctx).toString();
        }

        @Override
        public String getTypeName(CompileUnitParser.PrimitiveTypeEnumContext ctx) {
            return ((CompileUnitParser.LongTypeContext) ctx).Long().getText();
        }
    }

    static class FloatTypeVisitor implements PrimitiveTypeInternalVisitor {

        @Override
        public String visit(CompileUnitParser.PrimitiveTypeEnumContext ctx, CompileUnitVisitor visitor) {
            return visitor.visitFloatType((CompileUnitParser.FloatTypeContext) ctx).toString();
        }

        @Override
        public String getTypeName(CompileUnitParser.PrimitiveTypeEnumContext ctx) {
            return ((CompileUnitParser.FloatTypeContext) ctx).Float().getText();
        }
    }

    static class DoubleTypeVisitor implements PrimitiveTypeInternalVisitor {


        @Override
        public String visit(CompileUnitParser.PrimitiveTypeEnumContext ctx, CompileUnitVisitor visitor) {
            return visitor.visitDoubleType((CompileUnitParser.DoubleTypeContext) ctx).toString();
        }

        @Override
        public String getTypeName(CompileUnitParser.PrimitiveTypeEnumContext ctx) {
            return ((CompileUnitParser.DoubleTypeContext) ctx).Double().getText();
        }
    }


    static class AnyTypeVisitor implements PrimitiveTypeInternalVisitor {


        @Override
        public String visit(CompileUnitParser.PrimitiveTypeEnumContext ctx, CompileUnitVisitor visitor) {
           return  visitor.visitAnyType((CompileUnitParser.AnyTypeContext) ctx).toString();
        }

        @Override
        public String getTypeName(CompileUnitParser.PrimitiveTypeEnumContext ctx) {
            return ((CompileUnitParser.AnyTypeContext) ctx).Any().getText();
        }
    }

}
